package main

import (
	"encoding/json"
	"errors"
	"reflect"
)

type JObject struct {
	data map[string]interface{}
}

type InvalidJObjectError struct {
	Type reflect.Type
}

func (e *InvalidJObjectError) Error() string {
	if e.Type == nil {
		return "json: New(nil)"
	}

	if e.Type.Kind() != reflect.Ptr {
		return "json: New(non-pointer " + e.Type.String() + ")"
	}
	return "json: New(nil " + e.Type.String() + ")"
}

func (o *JObject) New(data []byte) error {
	o.data = make(map[string]interface{})

	return json.Unmarshal(data, &o.data)
}

func (o *JObject) Get(key string) (interface{}, error) {
	if v, ok := o.data[key]; ok {
		return v, nil
	} else {
		return nil, errors.New("no field")
	}
}

func (o *JObject) GetString(key string) (string, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(string); ok1 {
			return v1, nil
		} else {
			return "", errors.New("not string")
		}
	} else {
		return "", errors.New("no field")
	}
}

func (o *JObject) GetBool(key string) (bool, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(bool); ok1 {
			return v1, nil
		} else {
			return false, errors.New("not bool")
		}
	} else {
		return false, errors.New("no field")
	}
}

func (o *JObject) GetInt(key string) (int, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(int); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not int")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetInt8(key string) (int8, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(int8); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not int8")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetInt16(key string) (int16, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(int16); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not int16")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetInt32(key string) (int32, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(int32); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not int32")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetInt64(key string) (int64, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(int64); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not int64")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetByte(key string) (byte, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(byte); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not byte")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetUint16(key string) (uint16, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(uint16); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not uint16")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetUint32(key string) (uint32, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(uint32); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not uint32")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetUint64(key string) (uint64, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(uint64); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not uint64")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetFloat32(key string) (float32, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(float32); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not float32")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetFloat64(key string) (float64, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(float64); ok1 {
			return v1, nil
		} else {
			return 0.0, errors.New("not float64")
		}
	} else {
		return 0.0, errors.New("no field")
	}
}

func (o *JObject) GetComplex64(key string) (complex64, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(complex64); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not complex64")
		}
	} else {
		return 0, errors.New("no field")
	}
}

func (o *JObject) GetComplex128(key string) (complex128, error) {
	if v, ok := o.data[key]; ok {
		if v1, ok1 := v.(complex128); ok1 {
			return v1, nil
		} else {
			return 0, errors.New("not complex128")
		}
	} else {
		return 0, errors.New("no field")
	}
}
